package net.jjjshop.front.service.user.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.ApiModelProperty;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.bean.WxOAuth2UserInfo;
import me.chanjar.weixin.common.error.WxErrorException;
import net.jjjshop.common.constants.ConfConstants;
import net.jjjshop.common.constants.SmsConstants;
import net.jjjshop.common.entity.Sms;
import net.jjjshop.common.entity.app.App;
import net.jjjshop.common.entity.lbt.*;
import net.jjjshop.common.entity.user.User;
import net.jjjshop.common.entity.user.UserGrade;
import net.jjjshop.common.entity.user.UserPointsLog;
import net.jjjshop.common.enums.SettingEnum;
import net.jjjshop.common.mapper.user.UserMapper;
import net.jjjshop.common.service.lbt.*;
import net.jjjshop.common.settings.vo.PointsVo;
import net.jjjshop.common.util.BigDecimalUtil;
import net.jjjshop.common.util.SettingUtils;
import net.jjjshop.common.util.UserUtils;
import net.jjjshop.common.util.common.CommonUtil;
import net.jjjshop.common.util.wx.AppWxUtils;
import net.jjjshop.config.constant.CommonConstant;
import net.jjjshop.config.constant.CommonRedisKey;
import net.jjjshop.config.properties.JwtProperties;
import net.jjjshop.config.properties.SpringBootJjjProperties;
import net.jjjshop.framework.common.exception.BusinessException;
import net.jjjshop.framework.common.service.impl.BaseServiceImpl;
import net.jjjshop.framework.core.util.RequestDetailThreadLocal;
import net.jjjshop.framework.shiro.cache.UserLoginRedisService;
import net.jjjshop.framework.shiro.jwt.JwtToken;
import net.jjjshop.framework.shiro.util.JwtTokenUtil;
import net.jjjshop.framework.shiro.util.JwtUtil;
import net.jjjshop.framework.shiro.util.SaltUtil;
import net.jjjshop.framework.shiro.vo.LoginUserVo;
import net.jjjshop.framework.util.LoginUtil;
import net.jjjshop.framework.util.PasswordUtil;
import net.jjjshop.front.param.AppWxParam;
import net.jjjshop.front.param.user.LineUpParam;
import net.jjjshop.front.param.user.PhoneRegisterParam;
import net.jjjshop.front.service.app.AppService;
import net.jjjshop.front.service.user.SmsService;
import net.jjjshop.front.service.user.UserGradeService;
import net.jjjshop.front.service.user.UserPointsLogService;
import net.jjjshop.front.service.user.UserService;
import net.jjjshop.front.vo.user.LoginUserTokenVo;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.text.StringEscapeUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

/**
 * 用户记录表 服务实现类
 *
 * @author jjjshop
 * @since 2022-07-01
 */
@Slf4j
@Service
public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implements UserService {

    @Lazy
    @Autowired
    private SpringBootJjjProperties springBootJjjProperties;
    @Lazy
    @Autowired
    private JwtProperties jwtProperties;
    @Lazy
    @Autowired
    private RedisTemplate redisTemplate;
    @Lazy
    @Autowired
    private UserLoginRedisService userLoginRedisService;
    @Lazy
    @Autowired
    private WxMaService wxMaService;
    @Lazy
    @Autowired
    private AppWxUtils appWxUtils;
    @Lazy
    @Autowired
    private UserGradeService userGradeService;
    @Lazy
    @Autowired
    private SettingUtils settingUtils;
    @Lazy
    @Autowired
    private UserUtils userUtils;
    @Lazy
    @Autowired
    private UserPointsLogService userPointsLogService;
    @Lazy
    @Autowired
    private SmsService smsService;
    @Autowired
    private AppService appService;
    @Autowired
    private LbLineUpService lbLineUpService;
    @Autowired
    private LbPublicUpCancelService publicUpCancelService;
    @Resource
    private LbUserWalletService lbUserWalletService;
    @Resource
    private LbLineClassService lbLineClassService;
    @Autowired
    private TransactionTemplate transactionTemplate;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserBillService userBillService;

    @Autowired
    private LbSysConfigService sysConfigService;
    /**
     * 手机号密码登录
     *
     * @param mobile
     * @param password
     * @return
     */
    public LoginUserTokenVo login(String mobile, String password) {
        Long appId = RequestDetailThreadLocal.getRequestDetail().getAppId();
        if(appId == null){
            throw new BusinessException("appId不能为空");
        }
        List<User> userList = this.list(new LambdaQueryWrapper<User>()
                .eq(User::getMobile, mobile)
                .ne(User::getPassword, "")
                .eq(User::getAppId, appId)
        );
        if (userList.size() == 0) {
            throw new AuthenticationException("用户名不存在");
        }
        User user = userList.get(0);
        String encryptPassword = PasswordUtil.encrypt(password, user.getSalt());
        if (!encryptPassword.equals(user.getPassword())) {
            throw new AuthenticationException("用户名或密码错误");
        }
        App app = appService.getOne(new LambdaQueryWrapper<App>().eq(App::getAppId,user.getAppId())
                .comment(CommonConstant.NOT_WITH_App_Id));
        if (app == null) {
            throw new BusinessException("登录失败, 未找到应用信息");
        }
        if (app.getIsDelete()) {
            throw new BusinessException("登录失败, 当前应用已删除");
        }
        if(!app.getIsRecycle()){
            throw new BusinessException("登录失败, 当前应用已禁用");
        }
        if (app.getExpireTime() != null && app.getExpireTime().before(new Date())) {
            throw new BusinessException("登录失败, 当前应用已过期，请联系平台续费");
        }
        return this.getLoginUserTokenVo(user);
    }

    /**
     * 获取登陆用户token
     *
     * @param user
     * @return
     */
    private LoginUserTokenVo getLoginUserTokenVo(User user) {
        // 将系统用户对象转换成登录用户对象
        LoginUserVo loginUserVo = new LoginUserVo();
        BeanUtils.copyProperties(user, loginUserVo);
        // 获取数据库中保存的盐值
        String newSalt = SaltUtil.getSalt(user.getSalt(), jwtProperties);

        // 生成token字符串并返回
        Long expireSecond = jwtProperties.getExpireSecond();
        String token = JwtUtil.generateToken("" + user.getUserId(), newSalt, Duration.ofSeconds(expireSecond));
        log.debug("token:{}", token);

        // 创建AuthenticationToken
        JwtToken jwtToken = JwtToken.build(token, "" + user.getUserId(), newSalt, expireSecond);

        boolean enableShiro = springBootJjjProperties.getShiro().isEnable();
        if (enableShiro) {
            // 从SecurityUtils里边创建一个 subject
            Subject subject = SecurityUtils.getSubject();
            // 执行认证登录
            subject.login(jwtToken);
        } else {
            log.warn("未启用Shiro");
        }

        // 缓存登录信息到Redis
        userLoginRedisService.cacheLoginInfo(jwtToken, loginUserVo);
        log.debug("登录成功,userId:{}", "" + user.getUserId());

        // 缓存登录信息到redis
        String tokenSha256 = DigestUtils.sha256Hex(token);
        redisTemplate.opsForValue().set(tokenSha256, loginUserVo, 1, TimeUnit.DAYS);

        // 返回token和登录用户信息对象
        LoginUserTokenVo loginUserTokenVo = new LoginUserTokenVo();
        loginUserTokenVo.setToken(token);
        loginUserTokenVo.setLoginUserVo(loginUserVo);
        return loginUserTokenVo;
    }

    /**
     * 微信小程序登录
     *
     * @param appWxParam
     * @return
     */
    public LoginUserTokenVo loginWx(AppWxParam appWxParam) {
        try {
            WxMaJscode2SessionResult result = wxMaService.switchoverTo(appWxUtils.getConfig(wxMaService, null)).getUserService().getSessionInfo(appWxParam.getCode());
            // 查找用户是否存在，不存在则先注册
            User user = null;
            //先通过unionId查找
            if (StringUtils.isNotBlank(result.getUnionid())) {
                user = getUserByUnionId(result.getUnionid());
            }
            if (user == null) {
                // 通过你openId查找
                user = this.getOne(new LambdaQueryWrapper<User>().eq(User::getOpenId, result.getOpenid()));
            }
            if (user != null) {
                return this.getLoginUserTokenVo(user);
            } else {
                // 注册后返回
                String userInfoStr = StringEscapeUtils.unescapeHtml4(appWxParam.getUserInfo());
                JSONObject userInfo = JSONObject.parseObject(userInfoStr);
                User bean = new User();
                if (StringUtils.isNotBlank(result.getUnionid())) {
                    bean.setUnionId(result.getUnionid());
                }
                bean.setOpenId(result.getOpenid());
                bean.setNickname(userInfo.getString("nickName"));
                bean.setAvatarurl(userInfo.getString("avatarUrl"));
                bean.setRegSource("wx");
                this.save(bean);
                this.afterReg(appWxParam.getRefereeId());
                return this.getLoginUserTokenVo(bean);
            }
        } catch (WxErrorException e) {
            log.info("微信小程序登录异常：", e.getMessage());
            return null;
        }
    }

    /**
     * 微信公众号登录
     * @param wxMpUser
     * @return
     */
    public LoginUserTokenVo loginMp(WxOAuth2UserInfo wxMpUser, Integer refereeId){
        User user = null;
        // 查找用户是否存在，不存在则先注册
        //先通过unionId查找
        if(StringUtils.isNotBlank(wxMpUser.getUnionId())){
            user = getUserByUnionId(wxMpUser.getUnionId());
        }
        if (user == null) {
            // 通过你openId查找
            user = this.getOne(new LambdaQueryWrapper<User>().eq(User::getMpopenId, wxMpUser.getOpenid()));
        }
        if (user != null) {
            return this.getLoginUserTokenVo(user);
        } else {
            // 注册后返回
            User bean = new User();
            if (StringUtils.isNotBlank(wxMpUser.getUnionId())) {
                bean.setUnionId(wxMpUser.getUnionId());
            }
            bean.setMpopenId(wxMpUser.getOpenid());
            bean.setNickname(wxMpUser.getNickname());
            bean.setAvatarurl(wxMpUser.getHeadImgUrl());
            bean.setRegSource("mp");
            this.save(bean);
            this.afterReg(refereeId);
            return this.getLoginUserTokenVo(bean);
        }
    }

    /**
     * 手机号验证码登录
     * @param mobile
     * @param code
     * @return
     */
    public LoginUserTokenVo loginSms(String mobile, String code){
        // 校验验证码
        this.check(mobile, code);
        List<User> userList = this.list(new LambdaQueryWrapper<User>().eq(User::getMobile, mobile)
                .orderByAsc(User::getCreateTime));
        if(userList.size() == 0){
            throw new BusinessException("手机号不存在");
        }
        User user = userList.get(0);
        if (user.getIsDelete() == 1) {
            throw new BusinessException("手机号被禁止或删除，请联系客服");
        }
        return this.getLoginUserTokenVo(user);
    }

    /**
     * 累积用户的可用积分
     */
    public Boolean setIncPoints(Integer userId, Integer points, String describe, Boolean upgrade){
        //新增积分变动明细
        UserPointsLog pointsLog = new UserPointsLog();
        pointsLog.setUserId(userId);
        pointsLog.setValue(points);
        pointsLog.setDescription(describe);
        userPointsLogService.save(pointsLog);
        //更新用户可用积分
        User user = this.getById(userId);
        user.setPoints(Math.max(user.getPoints() + points, 0));
        if(points>0){
            user.setTotalPoints(user.getTotalPoints()+points);
        }
        this.updateById(user);
        return true;
    }

    //h5注册
    @Override
    public boolean phoneRegister(PhoneRegisterParam phoneRegisterParam) {
        // 校验验证码
        this.checkSms(phoneRegisterParam.getMobile(), phoneRegisterParam.getCode(),"register");
        int count = this.count(new LambdaQueryWrapper<User>().eq(User::getMobile, phoneRegisterParam.getMobile()));
        if (!(count > 0)) {
            User user = new User();
            user.setMobile(phoneRegisterParam.getMobile());
            user.setRegSource(phoneRegisterParam.getRegSource() != null ? phoneRegisterParam.getRegSource() : "app");
            user.setGradeId(userGradeService.getDefaultGradeId());
            user.setPassword(DigestUtils.md5Hex(phoneRegisterParam.getPassword()));
            // 盐值
            String salt = SaltUtil.generateSalt();
            // 密码加密
            user.setSalt(salt);
            user.setPassword(PasswordUtil.encrypt(phoneRegisterParam.getPassword(), salt));
            if (org.apache.commons.lang3.StringUtils.isEmpty(phoneRegisterParam.getNickname())){
                user.setNickname("用户:"+phoneRegisterParam.getMobile());
            }else {
                user.setNickname(phoneRegisterParam.getNickname());
            }
            user.setInviteCode(generateInviteCode(6));

            User userParent = getUserInviteCode(phoneRegisterParam.getInviteCode());
            if (userParent == null || phoneRegisterParam.getInviteCode() == null){
                throw new BusinessException("推荐人不存在");
            }
            user.setRefereeId(userParent.getUserId());

            this.save(user);
            this.afterReg(user.getUserId());
            LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(User::getMobile,user.getMobile());
            List<User> list = list(wrapper);
            if (list != null && !list.isEmpty() ){
                lbUserWalletService.add(list.get(0).getUserId());
            }

            Boolean execute = transactionTemplate.execute(e -> {
                User byPhone = getByPhone(user.getMobile());
                if (null == userParent.getAline()){
                    byPhone.setPid(userParent.getUserId());
                    userParent.setAline(byPhone.getUserId());
                    updateById(byPhone);
                    updateById(userParent);
                }else if (null == userParent.getBline()){
                    byPhone.setPid(userParent.getUserId());
                    userParent.setBline(byPhone.getUserId());
                    updateById(byPhone);
                    updateById(userParent);
                }else if (null == userParent.getCline()){
                    byPhone.setPid(userParent.getUserId());
                    userParent.setCline(byPhone.getUserId());
                    updateById(byPhone);
                    updateById(userParent);
                }else{
                    //如果三条线都安置完成了后，就开始往C线的AB线安置
                return     setLineDs(byPhone,userParent.getCline());

                }

                return Boolean.TRUE;
            });
            if (!execute) {
                throw new BusinessException("创建用户失败!");
            }

            return true;
        } else {
            throw new BusinessException("手机号已存在");
        }
    }

    private boolean setLineDs(User byPhone,Integer cid){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", cid);
        User userParent = baseMapper.selectOne(queryWrapper);

        if (null == userParent.getAline()){
            byPhone.setPid(userParent.getUserId());
            userParent.setAline(byPhone.getUserId());
            updateById(byPhone);
            updateById(userParent);
            return true;
        }else if (null == userParent.getBline()){
            byPhone.setPid(userParent.getUserId());
            userParent.setBline(byPhone.getUserId());
            updateById(byPhone);
            updateById(userParent);
            return true;
        }else{

            int randomInt = ThreadLocalRandom.current().nextInt(2);
            //如果三条线都安置完成了后，就开始往C线的AB线安置
            if (randomInt == 0){
                return   setLineDs(byPhone,userParent.getAline());
            }else{
                return   setLineDs(byPhone,userParent.getBline());
            }


        }
    }
    /**
     * 验证短信
     */
    private Boolean checkSms(String mobile, String code,String type) {
        if (code.equals("871030") && SmsConstants.IS_OPEN_DEBUG){
           return true;
        }
        if (type.equals(SmsConstants.SMS_CONFIG_TYPE_VERIFICATION_TYPE)) {// 注册验证码
            Object object = redisTemplate.opsForValue().get(SmsConstants.SMS_REGISTER_KEY + "" + mobile);
            if (object == null){
                throw new BusinessException("验证码不正确");
            }
            if (code.equals(object.toString())) {
                return true;
            }
        }
        if (type.equals(SmsConstants.SMS_CONFIG_TYPE_SETPAYPASS_TYPE)) {// 设置支付密码验证码
            Object object = redisTemplate.opsForValue().get(SmsConstants.SMS_SETPAYPASS_KEY + "" + mobile);
            if (object == null){
                throw new BusinessException("验证码不正确");
            }
            if (code.equals(object.toString())) {
                return true;
            }
        }
        if (type.equals(SmsConstants.SMS_CONFIG_TYPE_RESET_TYPE)) {// 设置支付密码验证码
            Object object = redisTemplate.opsForValue().get(SmsConstants.SMS_RESET_KEY + "" + mobile);
            if (object == null){
                throw new BusinessException("验证码不正确");
            }
            if (code.equals(object.toString())) {
                return true;
            }
        }
        throw new BusinessException("验证码不正确");
    }

    /**
     * 邀请码
     * @return
     */
    public String generateInviteCode(int len) {
        String inviteCode = CommonUtil.getReturnCode(len);
        while (true) {
            User user = getUserInviteCode(inviteCode);
            if(user == null){
                break;
            }else{
                inviteCode = CommonUtil.getReturnCode(len);
            }
        }
        return inviteCode;
    }
    //查询邀请码
    public User getUserInviteCode(String code) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("invite_code", code);
        User user = baseMapper.selectOne(queryWrapper);
        return user;
    }

    /**
     * 注册之后的操作
     */
    public Boolean afterReg(Integer userId) {
        JSONObject setting = settingUtils.getSetting(SettingEnum.POINTS.getKey(), null);
        PointsVo pointsVo = setting.toJavaObject(PointsVo.class);
        if (pointsVo.getRegisterPoints() > 0) {
            userUtils.setIncPoints(userId, pointsVo.getRegisterPoints(), "新用户注册赠送", true);
        }
        return true;
    }

    /**
     * 累计邀请数
     */
    public Boolean setIncInvite(Integer userId) {
        User user = this.getById(userId);
        user.setTotalInvite(user.getTotalInvite() + 1);
        return this.updateById(user);
    }

    /**
     * 验证
     */
    private Boolean check(String mobile, String code) {
        //判断验证码是否过期、是否正确
        List<Sms> smsList = smsService.list(new LambdaQueryWrapper<Sms>().eq(Sms::getMobile, mobile)
                .orderByDesc(Sms::getCreateTime).last("LIMIT 0,1"));
        if(smsList.size() == 0){
            return true;
            //throw new BusinessException("未查到短信发送记录");
        }
        Sms sms = smsList.get(0);
        double minuters = Double.valueOf((new Date()).getTime() - sms.getCreateTime().getTime())/60000;
        if(minuters > 30){
            throw new BusinessException("短信验证码超时");
        }
        if(!code.equals(sms.getCode())){
            throw new BusinessException("验证码不正确");
        }
        return true;
    }


    /**
     * 通过unionid查找用户
     *
     * @param unionId
     * @return
     */
    private User getUserByUnionId(String unionId) {
        if (StringUtils.isNotBlank(unionId)) {
            return this.getOne(new LambdaQueryWrapper<User>().eq(User::getUnionId, unionId));
        }
        return null;
    }

    /**
     * 修改密码
     * @param mobile
     * @param code
     * @param password
     * @return
     */
    public Boolean renew(String mobile, String code, String password) {
        this.check(mobile, code);
        List<User> userList = this.list(new LambdaQueryWrapper<User>().eq(User::getMobile, mobile)
                .orderByAsc(User::getCreateTime));
        if(userList.size() == 0){
            throw new BusinessException("手机号不存在");
        }
        User user = userList.get(0);
        if (user.getIsDelete() == 1) {
            throw new BusinessException("手机号被禁止或删除，请联系客服");
        }
        User updateUser = new User();
        updateUser.setUserId(user.getUserId());
        updateUser.setPassword(DigestUtils.md5Hex(password));
        return true;
    }

    /**
     * 退出
     *
     * @param request
     * @throws Exception
     */
    @Override
    public void logout(HttpServletRequest request) throws Exception {
        Subject subject = SecurityUtils.getSubject();
        //注销
        subject.logout();
        // 获取token
        String token = JwtTokenUtil.getToken(request,"");
        String username = JwtUtil.getUsername(token);
        // 删除Redis缓存信息
        deleteLoginInfo(token, username);
        log.info("登出成功,username:{},token:{}", username, token);
    }


    private void deleteLoginInfo(String token, String username) {
        if (token == null) {
            throw new IllegalArgumentException("token不能为空");
        }
        if (username == null) {
            throw new IllegalArgumentException("username不能为空");
        }
        String tokenMd5 = DigestUtils.md5Hex(token);
        // 1. delete tokenMd5
        redisTemplate.delete(String.format(CommonRedisKey.USER_LOGIN_TOKEN, tokenMd5));
        // 2. delete username
        redisTemplate.delete(String.format(CommonRedisKey.USER_LOGIN_USER, username));
        // 3. delete salt
        redisTemplate.delete(String.format(CommonRedisKey.USER_LOGIN_SALT, username));
        // 4. delete user token
        redisTemplate.delete(String.format(CommonRedisKey.USER_LOGIN_USER_TOKEN, username, tokenMd5));
    }

    /**
     * 修改用户信息
     *
     * @param userId
     * @param updateType
     * @param updateValue
     * @return
     */
    public Boolean updateInfo(Integer userId, String updateType, String updateValue) {
        User user = new User();
        user.setUserId(userId);
        if ("nickname".equals(updateType)) {
            user.setNickname(updateValue);
        } else if ("avatarurl".equals(updateType)) {
            user.setAvatarurl(updateValue);
        } else {
            return false;
        }
        return this.updateById(user);
    }



    /**
     * 获取sessionKey
     *
     * @param code
     * @return
     */
    public String getSessionKey(String code) {
        try {
            WxMaJscode2SessionResult sessionResult = wxMaService.switchoverTo(appWxUtils.getConfig(wxMaService, null)).getUserService().getSessionInfo(code);
            return sessionResult.getSessionKey();
        } catch (Exception e) {
            log.info("getSessionKey失败{}", e.getMessage());
            return "";
        }
    }

    /**
     * 绑定手机号
     *
     * @param sessionKey
     * @param encryptedData
     * @param iv
     * @return
     */
    public String bindMobileByWx(Integer userId, String sessionKey, String encryptedData, String iv) {
        try {
            WxMaPhoneNumberInfo result = wxMaService.getUserService().getPhoneNoInfo(sessionKey, encryptedData, iv);
            String mobile = result.getPhoneNumber();
            User updateUser = new User();
            updateUser.setUserId(userId);
            updateUser.setMobile(mobile);
            this.updateById(updateUser);
            return mobile;
        } catch (Exception e) {
            log.info("手机号解密失败{}", e.getMessage());
            return "";
        }
    }




    @Override
    public TeamBean queryTeam(Integer uid, BigDecimal payMonet) {
        return getNewTeam(uid,payMonet);
    }

    @Override
    public IPage<LbLineUp> queryUserUpList(LineUpParam lineUpParam) {
        Page<LbLineUp> pageUser = new Page<LbLineUp>(lineUpParam.getPage(), lineUpParam.getLimit());
        QueryWrapper<LbLineUp> wrapper = new QueryWrapper<>();
        Integer uid = LoginUtil.getLoginUserRedisVo().getUserId();
        if (null !=lineUpParam.getStatus()){
            wrapper.eq("status",lineUpParam.getStatus());
        }
        if (null != uid){
            wrapper.eq("uid",uid);
        }
//        if (null !=lineUpParam.getStoreId()){
//            wrapper.eq("pid",lineUpParam.getStoreId());
//        }
        wrapper.orderByAsc("id");
        IPage<LbLineUp> list = lbLineUpService.page(pageUser,wrapper);
        LbLineUp lbLineUpFinish = null;
        LbLineUp lbLineUpTotal = null;
        for (LbLineUp bean : list.getRecords()){
            if (bean.getStatus() == 0){
                Integer pdNum= lbLineUpService.pdNum(bean.getCreateTime(),lineUpParam.getStoreId());
                bean.setPdNum(pdNum);
            }

            lbLineUpFinish  = new LbLineUp();
            lbLineUpFinish.setStatus(2);
            lbLineUpFinish.setId(bean.getId());
            lbLineUpFinish.setPid(lineUpParam.getStoreId());
            Integer countFinish = lbLineUpService.getCount(lbLineUpFinish);
            bean.setFinishNum(countFinish == null || countFinish == 0 ?1:countFinish);

            lbLineUpTotal = new LbLineUp();
            lbLineUpTotal.setId(bean.getId());
            lbLineUpTotal.setPid(lineUpParam.getStoreId());
            Integer countTotal = lbLineUpService.getCount(lbLineUpTotal);
            bean.setTotalNum(countTotal);
        }
        return list;
    }

    @Override
    public Integer cancelUp(LbLineUpRequest request) {
        Integer yf = 15;
        //偏远地区需要收多的邮费
        if (request.getAddress().contains("新疆")||request.getAddress().contains("西藏")||
                request.getAddress().contains("甘肃")||request.getAddress().contains("内蒙古")){
            yf = 30;
        }
        LbLineUp byId = lbLineUpService.getById(request.getId());
        if (null == byId){
            return null;
        }
        if (byId.getStatus()== 0){
            byId.setStatus(3);
            if (lbLineUpService.updateById(byId)){
                LbPublicUpCancelEntity publicUpCancel = new LbPublicUpCancelEntity();
                publicUpCancel.setOrderId(byId.getOrderId());
                publicUpCancel.setFreight(new BigDecimal(yf));
                publicUpCancel.setUserAddress(request.getAddress());
                publicUpCancel.setUserPhone(request.getPhone());
                publicUpCancel.setRealName(request.getAccount());
                publicUpCancel.setCreateTime(new Date());

                publicUpCancel.setProvinceId(request.getProvinceId());
                publicUpCancel.setCityId(request.getCityId());
                publicUpCancel.setRegionId(request.getRegionId());

                publicUpCancelService.save(publicUpCancel);
                return yf;
            }
        }
        return 0;
    }

    /**
     * 用户中心
     * @return UserCenterResponse
     */
    @Override
    public UserTeamResponse getUserTeam() {
        User currentUser =getById(LoginUtil.getLoginUserRedisVo().getUserId());
        if (ObjectUtil.isNull(currentUser)) {
            throw new BusinessException("您的登录已过期，请先登录");
        }
        User parentUser = getById(currentUser.getRefereeId());
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("referee_id", currentUser.getUserId());
        Integer ztCount = count(queryWrapper);


        UserTeamResponse userTeamResponse = new UserTeamResponse();
        userTeamResponse.setZtUserCount(ztCount);
        userTeamResponse.setAllAv(currentUser.getAllAv());

        userTeamResponse.setUser(parentUser);
//        List<User> tjUid = getTjUid(currentUser.getUserId());
//        List<Integer> uidList = new ArrayList<>();
//        for (User user : tjUid){
//            uidList.add(user.getUserId());
//        }
//        if (!uidList.isEmpty()){
//            BigDecimal lineMoney = userMapper.getLineMoney(uidList);
//            userTeamResponse.setAllAv(lineMoney);
//        }else{
//            userTeamResponse.setAllAv(new BigDecimal(0));
//        }
        userTeamResponse.setAllAv(new BigDecimal(0));
//        if (null != currentUser.getAline()){
//            BigDecimal aline = getAline(currentUser.getAline());
//            if (null != aline){
//                all = BigDecimalUtil.addDouble(all,aline);
//            }
//        }
//        if (null != currentUser.getBline()){
//            BigDecimal bline = getAline(currentUser.getBline());
//            if (null != bline){
//                all = BigDecimalUtil.addDouble(all,bline);
//            }
//        }
//        if (null != currentUser.getCline()){
//            BigDecimal cline = getAline(currentUser.getCline());
//            if (null != cline){
//                all = BigDecimalUtil.addDouble(all,cline);
//            }
//        }


        return userTeamResponse;
    }

    @Override
    public Map<String, Object> getTeamData() {

        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(User::getMobile,User::getNickname,User::getAvatarurl,User::getUserId,User::getLevel4,User::getCity);
        wrapper.eq(User::getRefereeId,LoginUtil.getLoginUserRedisVo().getUserId());
        BigDecimal all = new BigDecimal(0);
        List<User> list = list(wrapper);
        if (null != list && !list.isEmpty()){
            for (User user : list){
                List<User> tjUid = getTjUid(user.getUserId());
                if (!tjUid.isEmpty()){
                    List<Integer> uidList = new ArrayList<>();
                    for (User u : tjUid){
                        uidList.add(u.getUserId());
                    }
                    BigDecimal lineMoney = userMapper.getLineMoney(uidList);
                    if (null !=lineMoney){
                        user.setCity(lineMoney.toString());
                        all = BigDecimalUtil.addDouble(all,lineMoney);
                    }
                }
            }
        }
        List<Integer> a = new ArrayList<>();
        a.add(LoginUtil.getLoginUserRedisVo().getUserId());
        BigDecimal lineMoney = userMapper.getLineMoney(a);
        if (null !=lineMoney){
            all = BigDecimalUtil.addDouble(all,lineMoney);
        }
        Map<String,Object> map = new HashMap<>();
        map.put("list",list);
        map.put("money",all);
        return map;
    }

    /**
     * 新模式团队统计
     * @param
     * @return
     */
    private TeamBean getNewTeam(Integer uid,BigDecimal payMonet){
        // int all = 0;
        User byId = getById(uid);
        byId.setAllAv(BigDecimalUtil.addDouble(byId.getAllAv(),payMonet));
//        userDao.updateById(byId);
        TeamBean teamBean   = new TeamBean();
        teamBean.setNum(0);
        teamBean.setPrice(byId.getPayMoney());
        System.out.println("byId.getFirstPay()="+byId.getPayMoney());
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("referee_id", uid);
        List<User> list = this.list(queryWrapper);
        if (null != list && !list.isEmpty()){
            teamBean.setNum(list.size());
            for (User user : list){

                if (user.getGradeId() == 1){
                    teamBean.setMdNum(1+teamBean.getMdNum());
                }
                if (user.getGradeId() == 2){
                    teamBean.setDlNum(1+teamBean.getDlNum());
                }
                if (user.getGradeId() == 3){
                    teamBean.setHhNum(1+teamBean.getHhNum());
                }
                if (user.getGradeId() == 4){
                    teamBean.setDsNum(1+teamBean.getDsNum());
                }
            }
        }
//
        if (byId.getAllAv().doubleValue() > 50000){
            if (byId.getAllAv().doubleValue() > 3200000 && teamBean.getHhNum() >= 2){
//                teamBean.setDsNum(teamBean.getDsNum()+1);
                if (byId.getLevel() <4){
                    byId.setLevel(4);
                }

            }else
            if (byId.getAllAv().doubleValue() > 800000 && teamBean.getDlNum() >= 2){
//                teamBean.setHhNum(teamBean.getHhNum()+1);
                if (byId.getLevel() <3){
                    byId.setLevel(3);
                }
            }else
            if (byId.getAllAv().doubleValue() > 200000 && teamBean.getMdNum() >= 2){
//                teamBean.setDlNum(teamBean.getDlNum()+1);
                if (byId.getLevel() <2){
                    byId.setLevel(2);
                }
            }else
            if (byId.getAllAv().doubleValue() < 200000 || teamBean.getMdNum() < 2){
//                teamBean.setMdNum(teamBean.getMdNum()+1);
                if (byId.getLevel() <1){
                    byId.setLevel(1);
                }
            }

        }
        if (byId.getAllAv().doubleValue() > 10000000 && teamBean.getDsNum() >= 2){
            byId.setLevel(5);
            //这个8的是分红用户
        }
        LambdaQueryWrapper<UserGrade> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserGrade::getWeight,byId.getLevel());
        UserGrade one = userGradeService.getOne(wrapper);
        if (null != one){
            byId.setGradeId(one.getGradeId());
        }
        this.updateById(byId);

        return teamBean;
    }

    @Override
    public Boolean setPayPass(String phone, String smgCode,String payPass,String type) {
        this.checkSms(phone, smgCode, type);
        User byId = getById(LoginUtil.getUserId());
        byId.setPayPass(DigestUtils.md5Hex(payPass));
        return updateById(byId);
    }

    @Override
    public String setLoginPass(String phone, String smgCode,String payPass,String type) {
        this.checkSms(phone, smgCode, type);
        List<User> userList = this.list(new LambdaQueryWrapper<User>()
                        .eq(User::getMobile, phone)
                        .eq(User::getAppId, 10001));
        if (null == userList || userList.isEmpty()){
            return "未找到用户";
        }
        User byId =userList.get(0);
        byId.setPassword(PasswordUtil.encrypt(payPass, byId.getSalt()));
        byId.setPayPass(DigestUtils.md5Hex(payPass));
        boolean b = updateById(byId);
        if (b){
            return "200";
        }
        return "重置失败";
    }


    /**
     * 添加/扣减余额
     * @param uid      用户id
     * @param price    金额
     * @param nowMoney 历史金额
     * @param type     类型：add—添加，sub—扣减
     */
    @Override
    public Boolean operationBalance(Integer uid, BigDecimal price, BigDecimal nowMoney, String type) {
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        if (type.equals("add")) {
            updateWrapper.setSql(StrUtil.format("balance = balance + {}", price));
        } else {
            updateWrapper.setSql(StrUtil.format("balance = balance - {}", price));
            updateWrapper.last(StrUtil.format(" and (balance - {} >= 0)", price));
        }
        updateWrapper.eq("user_id", uid);
        updateWrapper.eq("balance", nowMoney);
        return update(updateWrapper);
    }
    @Override
    public Boolean operationCashMoney(Integer uid, BigDecimal price, BigDecimal nowMoney, String type) {
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        if (type.equals("add")) {
            updateWrapper.setSql(StrUtil.format("cash_money = cash_money + {}", price));
        } else {
            updateWrapper.setSql(StrUtil.format("cash_money = cash_money - {}", price));
            updateWrapper.last(StrUtil.format(" and (cash_money - {} >= 0)", price));
        }
        updateWrapper.eq("user_id", uid);
        updateWrapper.eq("cash_money", nowMoney);
        return update(updateWrapper);
    }

    @Override
    public List<LbLineClass> getLineClass() {
        return lbLineClassService.queryList();
    }

    /**
     * 根据手机号查询用户
     * @param phone 用户手机号
     * @return 用户信息
     */
    @Override
    public User getByPhone(String phone) {
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        lqw.eq(User::getMobile, phone);
        return userMapper.selectOne(lqw);
    }

    @Override
    public List<User> getLayer(Integer pid) {
        return null;
    }

    @Override
    public BigDecimal getAline(Integer uid) {
        User byId = getById(uid);
        Set<Integer> uid1 = getUid(byId);
        uid1.add(uid);
        if (null == uid1 || uid1.isEmpty()){
            return  new BigDecimal(0);
        }
        return userMapper.getLineMoney(new ArrayList<>(uid1));
    }

    @Override
    public BigDecimal getYjMoney(Integer uid) {
        List<User> tjUid = getTjUid(uid);
        List<Integer> uidList = new ArrayList<>();
        for (User user : tjUid){
            uidList.add(user.getUserId());
        }
        if (!uidList.isEmpty()){
            BigDecimal lineMoney = userMapper.getLineMoney(uidList);
           return  lineMoney;
        }
        return new BigDecimal(0);
    }


    private Set<Integer> getUid(User byId){
        Set<Integer> uidList = new HashSet<>();
        if (null!=byId&& null != byId.getAline()){
            uidList.add(byId.getAline());
            uidList.addAll(getUid(byId.getAline()));
        }
        if (null!=byId&& null != byId.getBline()){
            uidList.add(byId.getBline());
            uidList.addAll(getUid(byId.getBline()));
        }
        if (null!=byId&& null != byId.getCline()){
            uidList.add(byId.getCline());
            uidList.addAll(getUid(byId.getCline()));
        }
        return uidList;
    }

    private List<Integer> getUid(Integer uid){
        User byId = getById(uid);
        if (null == byId){
            return new ArrayList<>();
        }
        List<Integer> uidList = new ArrayList<>();
        if (null != byId.getAline()){
            uidList.add(byId.getAline());
            uidList.addAll(getUid(byId.getAline()));
        }
        if (null != byId.getBline()){
            uidList.add(byId.getBline());
            uidList.addAll(getUid(byId.getBline()));
        }
        if (null != byId.getCline()){
            uidList.add(byId.getCline());
            uidList.addAll(getUid(byId.getCline()));
        }

        return uidList;

    }


    private List<User> getTjUid(Integer uid){
        List<User> list = new ArrayList<>();
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(User::getUserId,User::getRefereeId);
        wrapper.eq(User::getRefereeId,uid);
        List<User> users = userMapper.selectList(wrapper);
        if (null != users && !users.isEmpty()){
            list.addAll(users);
            for (User user : users){
                List<User> tjUid = getTjUid(user.getUserId());
                list.addAll(tjUid);
            }
        }

        return list;

    }

}
